﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Timers;

namespace CarEmulator
{
    class Program
    {
        static Timer timer;

        //car state properties
        static int carId;
        static double x;
        static double y;
        static double speed;
        static double oilPressure;
        static double gasPressure;
        static DateTime time;
        static double direction;

        static int bufferSize;
        static Byte[] buffer; //buffer for sending information
        static Socket socket; //socket using to connect to the listener server
        static Random random; //random number generator

        static int count; //how many times information have been sent

        static int seconds; //interval between sending informations in seconds

        //args[0] - car id, args[1] - interval in seconds
        static void Main(string[] args)
        {
            //initialising variables
            count = 0;

            carId = Convert.ToInt32(args[0]);
            seconds = Convert.ToInt32(args[1]);
            x = 0;
            y = 0;
            speed = 10;
            oilPressure = 0;
            gasPressure = 0;
            time = DateTime.Now;
            direction = 0;


            bufferSize = sizeof(int) + 5*sizeof(double) + 6*sizeof(int) + sizeof(double);
            buffer = new Byte[bufferSize];
            

            random = new Random(DateTime.Now.Second + carId);
            timer = new Timer(seconds * 1000);
            timer.Start();
            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
            Console.WriteLine("Car ID : " + carId);
            while (true) ; 
        }

        private static void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            Console.WriteLine(count);
            count++;

            //generate random properties

                direction = random.NextDouble() * 2 * Math.PI;
                x = x + speed * Math.Sin(direction)/111;
                y = y + speed * Math.Cos(direction)/139;

            speed = speed + (random.NextDouble() * 20 - 10);

            oilPressure = random.NextDouble() * 10 + 100;
            
            gasPressure = random.NextDouble() * 10 + 100;
            
            time = DateTime.Now;

            //convert properties into byte arrays
            Byte[] carIdBytes = BitConverter.GetBytes(carId);
            Byte[] xBytes = BitConverter.GetBytes(x);
            Byte[] yBytes = BitConverter.GetBytes(y);
            Byte[] speedBytes = BitConverter.GetBytes(speed);
            Byte[] oilPressureBytes = BitConverter.GetBytes(oilPressure);
            Byte[] gasPressureBytes = BitConverter.GetBytes(gasPressure);
            Byte[] yearBytes = BitConverter.GetBytes(time.Year);
            Byte[] monthBytes = BitConverter.GetBytes(time.Month);
            Byte[] dayBytes = BitConverter.GetBytes(time.Day);
            Byte[] hourBytes = BitConverter.GetBytes(time.Hour);
            Byte[] minuteBytes = BitConverter.GetBytes(time.Minute);
            Byte[] secondBytes = BitConverter.GetBytes(time.Second);
            Byte[] directionBytes = BitConverter.GetBytes(direction);

            //reverse arrays if little endian to send right information
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(carIdBytes);
                Array.Reverse(xBytes);
                Array.Reverse(yBytes);
                Array.Reverse(speedBytes);
                Array.Reverse(oilPressureBytes);
                Array.Reverse(gasPressureBytes);
                Array.Reverse(yearBytes);
                Array.Reverse(monthBytes);
                Array.Reverse(dayBytes);
                Array.Reverse(hourBytes);
                Array.Reverse(minuteBytes);
                Array.Reverse(secondBytes);
                Array.Reverse(directionBytes);
            }

            //put arrays into buffer
            int j = 0;
            for (int i = 0; i < sizeof(int); i++, j++)
                buffer[j] = carIdBytes[i];
            for (int i = 0; i < sizeof(double); i++, j++)
                buffer[j] = xBytes[i];
            for (int i = 0; i < sizeof(double); i++, j++)
                buffer[j] = yBytes[i];
            for (int i = 0; i < sizeof(double); i++, j++)
                buffer[j] = speedBytes[i];
            for (int i = 0; i < sizeof(double); i++, j++)
                buffer[j] = oilPressureBytes[i];
            for (int i = 0; i < sizeof(double); i++, j++)
                buffer[j] = gasPressureBytes[i];
            for (int i = 0; i < sizeof(int); i++, j++)
                buffer[j] = yearBytes[i];
            for (int i = 0; i < sizeof(int); i++, j++)
                buffer[j] = monthBytes[i];
            for (int i = 0; i < sizeof(int); i++, j++)
                buffer[j] = dayBytes[i];
            for (int i = 0; i < sizeof(int); i++, j++)
                buffer[j] = hourBytes[i];
            for (int i = 0; i < sizeof(int); i++, j++)
                buffer[j] = minuteBytes[i];
            for (int i = 0; i < sizeof(int); i++, j++)
                buffer[j] = secondBytes[i];
            for (int i = 0; i < sizeof(double); i++, j++)
                buffer[j] = directionBytes[i];

                //send information
                socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
            socket.Connect("", 3000);
            socket.Send(buffer, bufferSize, 0);
            socket.Disconnect(true);
            socket.Close();

            //start timer to send information again after specified seconds
            timer.Interval = seconds * 1000;
            timer.Start();
        }
    }
}
